#include <iostream>
#include <vector>
#include <mutex>
#include "Thread.hpp"

using namespace std;
using namespace ThreadModule;

int g_tickets = 10000; // 共享资源，没有保护的

class ThreadData
{
public:
    ThreadData(int &ticket, const string name, mutex &mutex) // 引用？？
        : _ticket(ticket), _name(name), _total(0), _mutex(mutex)
    {
    }

    ~ThreadData()
    {
    }

    int &_ticket;//不引用的话：每一次都是传入新的ticket也就是10000，那么每一个进程都有10000张票
    //引用的话：每次传入的是全局的g_ticket,会对ticket本身做出变化
    string _name;
    int _total;
    mutex &_mutex;
};

void route(ThreadData *td)
{
    while (true)
    {
        // LockGuard guard()
        // pthread_mutex_lock(&td->_mutex); // 加锁
        td->_mutex.lock(); // 加锁
        if (td->_ticket > 0)
        {
            usleep(100);
            // printf("%s running,get tickets:%d\n", td->_name.c_str(), td->_ticket);
            cout << td->_name.c_str() << " running,get tickst:" << td->_ticket << endl;
            td->_ticket--;
            // pthread_mutex_unlock(&td->_mutex); // 解锁
            td->_mutex.unlock(); // 解锁
            td->_total++;
        }
        else
        {
            td->_mutex.unlock(); // 解锁
            // pthread_mutex_unlock(&td->_mutex); // 解锁
            break;
        }
    }
}

const int num = 4;
int main()
{
    // std::cout << "main： &tickets: " << &g_tickets << std::endl;
    mutex mutex;

    std::vector<Thread<ThreadData *>> threads;
    vector<ThreadData *> datas;
    // 1. 创建一批线程
    for (int i = 0; i < num; i++)
    {
        std::string name = "thread-" + std::to_string(i + 1);
        ThreadData *td = new ThreadData(g_tickets, name, mutex);
        threads.emplace_back(route, td, name); // 模板为threadData*类型
        datas.emplace_back(td);
    }

    // 2. 启动 一批线程
    for (auto &thread : threads)
    {
        thread.Start();
    }

    // 3. 等待一批线程
    for (auto &thread : threads)
    {
        thread.Join();
        // std::cout << "wait thread done, thread is: " << thread.name() << std::endl;
    }
    sleep(1);

    // 4. 输出统计数据
    for (auto data : datas)
    {
        cout << data->_name << ":" << data->_total << endl;
        delete data;
    }

    return 0;
}

// class ThreadData
// {
// public:
//     ThreadData()
//     {}

//     ~ThreadData()
//     {}

// private:
//     int _tickets;
//     string _name;
//     int _total;
// };

// void route(int tickets)
// {
//     while (true)
//     {
//         if (tickets > 0)
//         {
//             usleep(1000);
//             printf("get tickets:%d\n",tickets);
//             tickets--;
//         }
//         else
//         {
//             break;
//         }
//     }
// }

// // int g_tickets = 10000;
// const int num = 4;

// int main()
// {
//     vector<Thread<int>> threads;
//     for (int i = 0; i < num; i++)
//     {
//         string name = "thread-" + to_string(i + 1);
//         threads.emplace_back(route, g_tickets, name);
//     }

//     for (auto thread : threads)
//     {
//         thread.Start();
//     }

//     for (auto thread : threads)
//     {
//         thread.Join();
//         cout << "wait thread done,thread is:" << thread.name() << endl;
//     }
//     return 0;
// }